package com.share.example.selenium.utils;

import com.share.common.utils.SysUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.html5.LocalStorage;
import org.openqa.selenium.html5.WebStorage;
import org.openqa.selenium.phantomjs.PhantomJSDriver;
import org.openqa.selenium.phantomjs.PhantomJSDriverService;
import org.openqa.selenium.remote.Augmenter;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;

import java.io.File;
import java.util.*;

/**
 * https://www.slimjet.com/chrome/google-chrome-old-version.php  谷歌浏览器下载地址
 * https://gfsoso.99lb.net/chrome.html  下载地址二
 * <p>
 * http://chromedriver.storage.googleapis.com/index.html  驱动下载地址
 */
@Slf4j
public class DriverUtil {
    private final static String CHROME_HOME = "C:\\Program Files\\Google\\Chrome\\application_chrome"; //谷歌浏览器程序
    private final static String CHROME_DRIVER_HOME = "C:\\Program Files\\Google\\Chrome\\application_chromedriver"; //驱动程序
    private final static String PHANTOMJS_HOME = "C:\\Program Files\\phantomjs"; //驱动程序

    private final int SCREEN_WITH = SysUtil.getScreenWith();
    private final int SCREENHEIGHT = SysUtil.getScreenHeight();

    private static Map<String, WebDriver> map = new HashMap<>();

    //重新缓存一个对象
    public static WebDriver reInitDriver(String name) {
        WebDriver oldDriver = map.get(name);
        if (oldDriver != null) {
            oldDriver.quit();
            oldDriver = null;
        }
        WebDriver driver = getDriver(name);
        map.put(name, driver);
        return driver;
    }

    public static WebDriver getDriver(String name) {
        WebDriver driver = map.get(name);
        if (driver != null) {
            return driver;
        } else {
            synchronized (name) {
                WebDriver dri = map.get(name);
                if (dri != null) {
                    return dri;
                }

                WebDriver tDriver = null;
                if (SysUtil.isWindows()) {
                    log.info("window环境加载chromeDriver");
                    tDriver = getIncognitoChromeDriver();
                } else {
                    log.info("linux环境加载phantomjsDriver");
                    tDriver = getPhantomjsDriver();
                }

                map.put(name, tDriver);
                return tDriver;
            }
        }
    }

    //初始化一个无界面的驱动程序
    private static WebDriver getPhantomjsDriver() {
        String phantomjsHome = System.getenv("PHANTOMJS_HOME");//System.getenv获取环境变量,仅idea重启才有效
        phantomjsHome = StringUtils.isEmpty(phantomjsHome) ? PHANTOMJS_HOME : phantomjsHome;
        String phantomjsPath = phantomjsHome + File.separator + (SysUtil.isWindows() ? "phantomjs.exe" : "phantomjs");
        log.info("PHANTOMJS_HOME={}", phantomjsHome);
        log.info("phantomjsPath={}", phantomjsPath);

        DesiredCapabilities desiredCapabilities = DesiredCapabilities.phantomjs();
        desiredCapabilities.setCapability(PhantomJSDriverService.PHANTOMJS_EXECUTABLE_PATH_PROPERTY, phantomjsPath);
        desiredCapabilities.setCapability(CapabilityType.ELEMENT_SCROLL_BEHAVIOR, true);
        desiredCapabilities.setCapability(CapabilityType.TAKES_SCREENSHOT, true);
        desiredCapabilities.setCapability(CapabilityType.ENABLE_PROFILING_CAPABILITY, true);
        desiredCapabilities.setCapability(CapabilityType.HAS_NATIVE_EVENTS, true);
        desiredCapabilities.setJavascriptEnabled(true);

        ArrayList<String> cliArgs = new ArrayList<>();
        cliArgs.add("--web-security=true");
        cliArgs.add("--ignore-ssl-errors=true");
        desiredCapabilities.setCapability(PhantomJSDriverService.PHANTOMJS_CLI_ARGS, cliArgs);

        PhantomJSDriver phantomJSDriver = new PhantomJSDriver(desiredCapabilities);
        return phantomJSDriver;
    }

    //无痕模式
    private static ChromeDriver getIncognitoChromeDriver() {
        //无痕模式
        String[] arr = {"--incognito"}; //无痕模式
        return getBaseChromeDriver(arr);
    }

    //实例化谷歌浏览器
    private static ChromeDriver getChromeDriver() {
        return getBaseChromeDriver(null);
    }

    private static ChromeDriver getBaseChromeDriver(String... paramOptions) {
        log.info("即将初始化一个chrome");
        //1.设置路径
        String chromeDriverHome = System.getenv("CHROME_DRIVER_HOME");
        chromeDriverHome = StringUtils.isEmpty(chromeDriverHome) ? CHROME_DRIVER_HOME : chromeDriverHome;
        String chromedriverPath = chromeDriverHome + File.separator + (SysUtil.isWindows() ? "chromedriver.exe" : "chromedriver");
        System.setProperty("webdriver.chrome.driver", chromedriverPath);
        //C:\Users\Administrator\Downloads\chromedriver_win32\chromedriver.exe
        log.info("CHROME_DRIVER_HOME={}", chromeDriverHome);
        log.info("chromedriverPath={}", chromedriverPath);

        ChromeOptions options = new ChromeOptions();

        //设置为开发者模式
        options.setExperimentalOption("excludeSwitches", Arrays.asList("enable-automation"));

        //指定浏览器分辨率
        options.addArguments("--start-maximized");

        //指定语言
        options.addArguments("--lang=zh-CN");

        //追加额外的参数
        if (paramOptions != null) {
            for (String param : paramOptions) {
                if (StringUtils.isNotBlank(param) && param.startsWith("-")) {
                    options.addArguments(param);
                }
            }
        }

        //指定用户信息缓存目录
        String chromeCacheHome = chromeDriverHome + "\\cache_data";
        options.addArguments("--user-data-dir=" + chromeCacheHome); //设置缓存用户文件目录
        options.addArguments("--disk-cache-dir=" + chromeCacheHome);// # 设置缓存硬盘文件目录
        log.info("disk-cache-dir={}", chromeCacheHome);

        //手动指定使用的浏览器位置---需要设置2个参数
//        options.addArguments("--no-sandbox");
        String chromeHome = System.getenv("CHROME_HOME");//System.getenv获取环境变量,仅idea重启才有效
        chromeHome = StringUtils.isEmpty(chromeHome) ? CHROME_HOME : chromeHome;
        String chromePath = chromeHome + File.separator + (SysUtil.isWindows() ? "chrome.exe" : "chrome");
        options.setBinary(chromePath);//C:\Users\Administrator\AppData\Local\Google\Chrome\Application\chrome.exe
        log.info("CHROME_HOME={}", chromeHome);
        log.info("chromePath={}", chromePath);

        ChromeDriver ggd = new ChromeDriver(options);

        //调整浏览器大小
//        Dimension dimension = new Dimension(SysUtil.getScreenWith(), SysUtil.getScreenHeight());
//        ggd.manage().window().setSize(dimension);

        return ggd;
    }


    //当浏览器打开了多个窗口，只想要关闭当前鼠标聚焦的窗口（句柄），则需要使用close方法。
    public static void closeTab(WebDriver driver) {
        driver.close();
    }

    //关闭当前所有的浏览器窗口，关闭浏览器驱动进程，销毁driver操作，则需要使用quit方法。
    public static void closeBrowser(WebDriver driver) {
        driver.quit();
    }

    //新增并切换到新选项卡
    public static String addNewTabAndSwitch(WebDriver driver) {
        Set<String> windowHandles = driver.getWindowHandles();

        JavascriptExecutor driver1 = (JavascriptExecutor) driver;
        driver1.executeScript("window.open();");

        Set<String> windowHandles_2 = driver.getWindowHandles();
        windowHandles_2.removeAll(windowHandles);

        String winId = windowHandles_2.stream().findFirst().get();
        driver.switchTo().window(winId);
        return winId;
    }

    //新增并切换到新选项卡 --- 并打开链接
    public static String newTabOpenUrl(WebDriver driver, String url) {
        String s = addNewTabAndSwitch(driver);
        driver.get(url);
        return s;
    }

    //https://blog.csdn.net/scut_yfli/article/details/107226221
    //播放视频
    public static void videoPlay(WebDriver driver, WebElement videoElement) {
        JavascriptExecutor js = (JavascriptExecutor) driver;
        js.executeScript("return arguments[0].play()", videoElement);
    }

    ////暂停视频
    public static void videoPause(WebDriver driver, WebElement videoElement) {
        JavascriptExecutor js = (JavascriptExecutor) driver;
        js.executeScript("arguments[0].pause()", videoElement);
    }

    //移动鼠标
    public static void mouseScrollTo(WebDriver driver, int x, int y) {
        String str = String.format("window.scrollTo(%s,%s)", x, y);
        ((JavascriptExecutor) driver).executeScript(str);
    }

    //操作水平滚动条
    public static void scrollLeft(WebDriver driver, int x) {
        String scroll = "document.documentElement.scrollLeft=" + x;
        JavascriptExecutor js = (JavascriptExecutor) driver;
        js.executeScript(scroll);
    }

    //操作垂直滚动条
    public static void scrollTop(WebDriver driver, int y) {
        String scroll = "document.documentElement.scrollTop=" + y;
        JavascriptExecutor js = (JavascriptExecutor) driver;
        js.executeScript(scroll);
    }

    //获取当前窗口
    public static String getWindow(WebDriver driver) {
        return driver.getWindowHandle();
    }

    //获取所有窗口
    public static Set<String> listWindows(WebDriver driver) {
        Set<String> handles = driver.getWindowHandles();
        return handles;
    }

    public static String[] listWindows2Array(WebDriver driver) {
        Set<String> sets = listWindows(driver);
        if (sets == null) {
            return null;
        } else {
            String[] arr = sets.toArray(new String[sets.size()]);
            return arr;
        }
    }


    //切换窗口
    public static void switchToTarget(WebDriver driver, String desTarget, String... currentTarget) {
        if (StringUtils.isNotEmpty(desTarget)) {
            driver.switchTo().window(desTarget);
            return;
        }

        String lastTarget = null;
        List<String> tagList = new LinkedList<>();
        if (currentTarget != null) {
            tagList = Arrays.asList(currentTarget);
        }
        Set<String> handles = driver.getWindowHandles();
        for (String actual : handles) {
            if (tagList.contains(actual)) {
                continue;
            }

            lastTarget = actual;
        }

        driver.switchTo().window(lastTarget);
    }

    //获取用户信息
    public static String getLocalStorage(WebDriver driver, String itemKey) {
        WebStorage augment = (WebStorage) new Augmenter().augment(driver);
        LocalStorage localStorage = augment.getLocalStorage();
        String strUserJson = localStorage.getItem(itemKey);
        return strUserJson;
    }
}
